﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System.Net;
using System;
using Volo.Abp;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.Authorization;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Validation;

namespace Leo.Awesome.AppPlatform.AbpExceptionHandler
{
    public class ApplicationHttpExceptionStatusCodeFinder : DefaultHttpExceptionStatusCodeFinder
    {
        public ApplicationHttpExceptionStatusCodeFinder(IOptions<AbpExceptionHttpStatusCodeOptions> options) 
            : base(options)
        {

        }
        public override HttpStatusCode GetStatusCode(
            HttpContext httpContext,
            Exception exception)
        {
            if (exception is IHasHttpStatusCode exceptionWithHttpStatusCode &&
                exceptionWithHttpStatusCode.HttpStatusCode > 0)
            {
                return (HttpStatusCode)exceptionWithHttpStatusCode.HttpStatusCode;
            }

            if (exception is IHasErrorCode exceptionWithErrorCode &&
                !exceptionWithErrorCode.Code.IsNullOrWhiteSpace())
            {
                if (Options.ErrorCodeToHttpStatusCodeMappings.TryGetValue(exceptionWithErrorCode.Code, out var status))
                {
                    return status;
                }
            }

            if (exception is AbpAuthorizationException)
            {
                return httpContext.User.Identity.IsAuthenticated
                    ? HttpStatusCode.Forbidden
                    : HttpStatusCode.Unauthorized;
            }

            //TODO: Handle SecurityException..?

            if (exception is AbpValidationException)
            {
                return HttpStatusCode.BadRequest;
            }

            if (exception is EntityNotFoundException)
            {
                return HttpStatusCode.NotFound;
            }

            if (exception is AbpDbConcurrencyException)
            {
                return HttpStatusCode.Conflict;
            }

            if (exception is NotImplementedException)
            {
                return HttpStatusCode.NotImplemented;
            }

            if (exception is IBusinessException)
            {
                return HttpStatusCode.Forbidden;
            }

            return HttpStatusCode.InternalServerError;
        }
    }
}
